<?php
/**
 * Limit the process numbers
 * this process is only can use in linux system
 * author: alacner zhang <alacner@gmail.com>

 Usage:
 PROCESS::limit($argv, 3);
 PROCESS::limit(__FILE__);
 PROCESS::limit(__FILE__, 1, true); //display debug info
*/
class PROCESS {
	public static function limit($process, $number = 1, $debug = false, $path = '/tmp/') {
		if (!preg_match('/linux/i', PHP_OS)) {
			printf("This function only use in linux system, but your system is %s\n", PHP_OS);
			return ;
			exit;
		}
		$process_str = is_array($process) ? implode(" ", $process) : $process;
		if (trim($process_str) == '') die('process can not specify, exit at ' . __FILE__);
		
		$debug_str = sprintf("process: %s\n", $process_str);
		$pfile = $path.sprintf("process_%s", md5($process_str));
		$debug_str .= sprintf("tmp file: %s\n", $pfile);
		$pids = @file($pfile);
	
		clearstatcache(); 
		$cPids = array(); 
		if (is_array($process)) {
			$process_tmp = array();
			foreach ($process as $p) {
				$process_tmp[] = preg_quote($p, '/');
			}
			$grep = implode(".*", $process_tmp);
		} else {
			$grep = preg_quote($process, '/');
		}
		
		is_array($pids) || $pids = array();
		foreach ($pids as $pid) {
			$pid = trim($pid);
			$proc = '/proc/'.$pid;
			if (is_numeric($pid) && file_exists($proc)) {
				$cmdline = file_get_contents($proc.'/cmdline');
				preg_match(sprintf("/%s/", $grep), $cmdline) && $cPids[] = $pid;
			}
		}
	
		if (count($cPids)) {
			$debug_str .= sprintf("process list: %s\n", @implode(',', $cPids));
		}
	
		$this_pid = (int)posix_getpid();
		$cPids[] = $this_pid;
		$debug_str .= sprintf("current pid: %d\n", $this_pid);
		$cPids_cnt = count($cPids);
		if ($number >= $cPids_cnt) {
			$debug_str .= sprintf("status: %d/%d, continue ...\n", $cPids_cnt, $number);
			if ($debug) echo $debug_str;
		} else {
			$debug_str .= sprintf("runing : %d, exit!\n", $number);
			if ($debug) echo $debug_str;
			exit;
		}
	
		$fp = fopen($pfile, 'wb');
		fwrite($fp, @implode("\n", $cPids));
		fclose($fp);
	}
}//end class
